Skip to main content

FP - 為什麼說函數是一等公民

函式是一等公民,這是什麼意思? 就是指 函式跟其他物件一樣 沒有什麼特別。 他可以儲存在陣列裏,當成參數傳遞,賦值給變數,你想怎麼樣都行。 這意味著可以將函數儲存在變數中,將他們傳遞給其他函數。

在變數中儲存函數

下面定義 add 函數將函數名稱 add 指派給 sum

function add(a, b) {
return a + b;
}

let sum = add;

我們可以正常的呼叫 add

let result = add(10, 20);

或者可以透過 sum 來呼叫

let result = sum(10, 20);

將函數傳給另一個函數

因為函數是值,所以可以將一個函數作為一個參數傳遞給另一個函數 下面聲明 average() 接收三個參數的函數。第三個參數是一個函數

function average(a, b, fn) {
return fn(a, b) / 2;
}

現在可以將 sum 傳遞給 average()

let result = average(10, 20, sum);

把它們放在一起

function add(a, b) {
return a + b;
}

let sum = add;

function average(a, b, fn) {
return fn(a, b) / 2;
}

let result = average(10, 20, sum);

console.log(result);
// 15

函數返回函數

由於函數是值,可以從一個函數傳回另一個函數 以下 compareBy() 函數回傳一個函數,用於兩個物件屬性比較

function compareBy(propertyName) {
return function (a, b) {
let x = a[propertyName],
y = b[propertyName];

if (x > y) {
return 1;
} else if (x < y) {
return -1;
} else {
return 0;
}
};
}

假如有一個產品物件陣列,其中每個產品物件都有兩個屬性 nameprice

let products = [
{ name: "iPhone", price: 900 },
{ name: "Samsung Galaxy", price: 850 },
{ name: "Sony Xperia", price: 700 },
];

可以透過 sort() 對於陣列進行排序,sort() 方法接收一個函數作為參數,用於比較陣列的兩個元素

例如:可以基於排序產品名稱 name 透過 compareBy() 傳遞 sort() 函數

// Sort by product name

products.sort(compareBy("name"));

console.table(products);

// 輸出如下:

// Products sorted by name:
┌─────────┬──────────────────┬───────┐
(index) │ name │ price │
├─────────┼──────────────────┼───────┤
0'Samsung Galaxy'850
1'Sony Xperia'700
2'iPhone'900
└─────────┴──────────────────┴───────┘

同樣,可以按價格對產品物件進行排序:

// Sort by product price

products.sort(compareBy('price'));
console.table(products);

// 輸出如下:

// Products sorted by price:
┌─────────┬──────────────────┬───────┐
(index) │ name │ price │
├─────────┼──────────────────┼───────┤
0'Sony Xperia'700
1'Samsung Galaxy'850
2'iPhone'900
└─────────┴──────────────────┴───────┘

JavaScript 函數是一等公民範例

以下範例定義了兩個函數,將以厘米為單位的長度轉換為英寸,反之亦然:

function cmToIn(length) {
return length / 2.54;
}

function inToCm(length) {
return length * 2.54;
}

下面的 convert() 函數有兩個參數。第一個參數是一個函數,第二個參數是長度。

function convert(fn, length) {
return fn(length);
}

要將 cm 轉換為 in,可以呼叫 convert() 函數並將 cmToIn 函數作為第一個函數傳遞給 convert()

let inches = convert(cmToIn, 10);
console.log(inches);

// 3.937007874015748

同樣 要把英吋轉為釐米 可以把 inToCm 函數傳遞給 convert()

let cm = convert(inToCm, 10);
console.log(cm);

// 25.4

結論

  • 函數是 javascript 的一等公民,可以稱這種程式為高階函式
  • 可以將函數作為參數傳遞給其他函數,將他們作為值從其他函數中返回,並將函數儲存在變數中